/**
  * @(#)SemesterCourses.java
  *
  * Store all of the courses and instructors for a given university 
  * registration term.
  *
  * @author Course Scheduler Team
  * 
  * @license GNU General Public License version 3 (GPLv3)
  *
  * This file is part of Course Scheduler, an open source, cross platform
  * course scheduling tool, configurable for most universities.
  *
  * Copyright (C) 2010-2012 Course Scheduler Team
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * 
  */
package com.pollicitus.scheduler.model;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.pollicitus.scheduler.model.Course;
import com.pollicitus.scheduler.model.Instructor;
import com.pollicitus.scheduler.model.Section;
import com.pollicitus.scheduler.model.SemesterCourses;
import com.pollicitus.scheduler.model.Term;


/**
 * Store all of the courses and instructors for a given university 
 * registration term.
 * 
 * @author Course Scheduler Team
 *
 */
public class SemesterCourses{

	/**
	 * The most recent revision in which this file was changed in the source control system
	 */
	public static final String _revision = "$LastChangedRevision: 539 $";
	
	/**
	 * The date on which this file was last changed and submitted to source control
	 */
	public static final String _date = "$LastChangedDate: 2011-11-19 23:14:16 -0500 (Sat, 19 Nov 2011) $";
	
	/**
	 * The user which last changed the file and committed the change to source control
	 */
	public static final String _author = "$LastChangedBy: mike@pollicitus.com $";
	
	/**
	 * The URL which can be used to access this specific file within the source control system
	 */
	public static final String _headURL = "$HeadURL: https://courseschedulerx.googlecode.com/svn/trunk/course-scheduler/course-scheduler-core/src/main/java/com/pollicitus/scheduler/model/SemesterCourses.java $";
	
	/**
	 * The source control file ID, comprised of the file name, latest revision, last changed date, and submitting user.
	 */
	public static final String _id = "$Id: SemesterCourses.java 539 2011-11-20 04:14:16Z mike@pollicitus.com $";
	
	//private storage
	private Map<String, Course> courses;
	private Map<Instructor, Instructor> profs;
	private Term term;
	private String university;
	
	/**
	 * Default constructor to initialize the Semester Courses object
	 */
	public SemesterCourses() {
		this.courses = new HashMap<String, Course>();
		this.profs = new HashMap<Instructor, Instructor>();
	}
	
	/**
	 * Return the registration term for the semester
	 * 
	 * @return the term
	 */
	public Term getTerm() {
		return term;
	}
	
	/**
	 * Set the registration term for the semester
	 * 
	 * @param term the term to use
	 */
	public void setTerm(Term term) {
		this.term = term;
	}

	/**
	 * Set the university for the semester course list
	 * 
	 * @param university the university to use
	 */
	public void setUniversity(String university) {
		this.university = university;
	}

	/**
	 * Return the university for the semester course list
	 * 
	 * @return the university
	 */
	public String getUniversity() {
		return university;
	}
	
	/**
	 * Return the number of courses for the university and registration term
	 * 
	 * @return number of courses
	 */
	public int getCourseCount() {
		return courses.size();
	}
	
	/**
	 * Return the number of instructors for the university and registration term
	 * 
	 * @return the number of instructors
	 */
	public int getInstructorCount(){
		return profs.size();
	}
	
	/**
	 * Return the courses which are available at the university for the registration term
	 * 
	 * @return the collection of courses
	 */
	public Collection<Course> getCourseList(){
		return courses.values();
	}
	
	/**
	 * Return the instructors which are teaching at the university for the registration term
	 * 
	 * @return the set of instructors
	 */
	public Collection<Instructor> getInstructorList(){
		return profs.values();
	}
	
	/**
	 * Add / consolidate the course into the semester course list.
	 * 
	 * If an existing course with the same ID exists, then consolidate onto
	 * a single course by changing instructors and consolidate the sections
	 * 
	 * If the course is new, then consolidate the instructor instances
	 */
	public void addCourse(Course course) {
		//check if the course is already stored
		if(this.courses.containsKey(course.getCourseID())) {
			//get the existing course
			Course temp = this.courses.get(course.getCourseID());
			
			//for each section, adjust the professor and add to existing
			for(Section item: course.getSections()) {
				adjustSectionProfessor(item);
				
				temp.addSection(item);
			}
		}else {
			//add the course to the map
			this.courses.put(course.getCourseID(), course);
			
			//for each section, adjust the professor if possible
			for(Section item: course.getSections()) {
				adjustSectionProfessor(item);
			}
		}
	}
	
	/**
	 * Return the course instance corresponding to the specified ID
	 * 
	 * @param courseID the course to return by ID
	 * @return the specified course
	 */
	public Course getCourse(String courseID) {
		return this.courses.get(courseID);
	}

	/**
	 * Adjust the section's professor to use a preexisting instance if
	 * available. Otherwise add the new professor
	 * 
	 * @param item the section to adjust professors
	 */
	private void adjustSectionProfessor(Section item){
		//get the section's prof and find an existing instance
		Instructor prof = item.getProf();
		Instructor stored = profs.get(prof);
		
		//set the prof on the section, if existing or store new prof
		if(stored != null){
			item.setProf(stored);
		}else{
			profs.put(prof, prof);
		}
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object o){
		SemesterCourses other = (SemesterCourses)o;
		
		return other.getUniversity().compareTo(this.getUniversity()) == 0 &&
				other.getTerm().equals(this.getTerm());
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode(){
		return getUniversity().hashCode() ^ getTerm().hashCode();
	}
}
